#include "main.h"

DS_TIME my_time;

void DS1302_Init(void)
{
	GPIO_Init(GPIOD, DS1302_RST, GPIO_MODE_OUT_PP_LOW_FAST);
	GPIO_Init(GPIOE, DS1302_CLK, GPIO_MODE_OUT_PP_LOW_FAST);
}

uint16_t DS1302_ReadReg(uint16_t addr)
{
	uint16_t i, temp= 0;
	GPIO_WriteHigh(GPIOD, DS1302_RST);
	addr = addr | 0x01;

	// Write Address
	GPIO_Init(GPIOE, DS1302_DAT, GPIO_MODE_OUT_PP_LOW_FAST);// set ds1302_dat pin as output
	for(i=0; i<8; i++)
	{
		if(addr & 0x01)
			GPIO_WriteHigh(GPIOE, DS1302_DAT);
		else
			GPIO_WriteLow(GPIOE, DS1302_DAT);
		GPIO_WriteHigh(GPIOE, DS1302_CLK);
		GPIO_WriteLow(GPIOE, DS1302_CLK);
		addr = addr >> 1;
	}

	// Read Data
	GPIO_Init(GPIOE, DS1302_DAT, GPIO_MODE_IN_FL_NO_IT );// set ds1302_dat pin as input
	for(i=0; i<8; i++)
	{
		temp = temp >> 1;
		if (GPIO_ReadInputPin(GPIOE, DS1302_DAT))
			temp |= 0x80;
		else
			temp &= 0x7F;
		GPIO_WriteHigh(GPIOE, DS1302_CLK);
		GPIO_WriteLow(GPIOE, DS1302_CLK);
	}

	GPIO_WriteLow(GPIOD, DS1302_RST);
	return temp;
}

void DS1302_WriteReg(uint16_t addr, uint16_t data)
{
	uint16_t i;
	GPIO_WriteHigh(GPIOD, DS1302_RST);
	addr = addr & 0xFE;

	// Write Address
	GPIO_Init(GPIOE, DS1302_DAT, GPIO_MODE_OUT_PP_LOW_FAST);// set ds1302_dat pin as output
	for(i=0; i<8; i++)
	{
		if(addr & 0x01)
			GPIO_WriteHigh(GPIOE, DS1302_DAT);
		else
			GPIO_WriteLow(GPIOE, DS1302_DAT);
		GPIO_WriteHigh(GPIOE, DS1302_CLK);
		GPIO_WriteLow(GPIOE, DS1302_CLK);
		addr = addr >> 1;
	}

	// Write Data
	for(i=0; i<8; i++)
	{
		if(data & 0x01)
			GPIO_WriteHigh(GPIOE, DS1302_DAT);
		else
			GPIO_WriteLow(GPIOE, DS1302_DAT);
		GPIO_WriteHigh(GPIOE, DS1302_CLK);
		GPIO_WriteLow(GPIOE, DS1302_CLK);
		data = data >> 1;
	}

	GPIO_WriteLow(GPIOD, DS1302_RST);
}

void DS1302_SetTime(uint16_t year, 
	uint16_t month, 
	uint16_t dayofmonth, 
	uint16_t hours, 
	uint16_t minutes, 
	uint16_t seconds)
{
	DS1302_WriteReg(DS1302_ADDR_CTRL, 0x00); // unprotected
	DS1302_WriteReg(DS1302_ADDR_SECONDS, 0x80);
	DS1302_WriteReg(DS1302_ADDR_MINUTES, minutes);
	DS1302_WriteReg(DS1302_ADDR_HOURS, hours);
	DS1302_WriteReg(DS1302_ADDR_DAYoM, dayofmonth);
	DS1302_WriteReg(DS1302_ADDR_MONTH, month);
	DS1302_WriteReg(DS1302_ADDR_YEAR, year);
	DS1302_WriteReg(DS1302_ADDR_SECONDS, seconds &0x7F);
	DS1302_WriteReg(DS1302_ADDR_CTRL, 0x80);
}

void DS1302_ReadTime(DS_TIME *my_time)
{
	my_time->year = DS1302_ReadReg(DS1302_ADDR_YEAR);
	my_time->month = DS1302_ReadReg(DS1302_ADDR_MONTH);
	my_time->dayofmonth = DS1302_ReadReg(DS1302_ADDR_DAYoM);
	my_time->hours = DS1302_ReadReg(DS1302_ADDR_HOURS);
	my_time->minutes = DS1302_ReadReg(DS1302_ADDR_MINUTES);
	my_time->seconds = DS1302_ReadReg(DS1302_ADDR_SECONDS)&0x7F;
}
